package com.enation.app.javashop.core.shop.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.enation.app.javashop.core.base.CachePrefix;
import com.enation.app.javashop.core.base.rabbitmq.AmqpExchange;
import com.enation.app.javashop.core.client.goods.GoodsClient;
import com.enation.app.javashop.core.client.system.RegionsClient;
import com.enation.app.javashop.core.goods.model.dos.CategoryDO;
import com.enation.app.javashop.core.goods.model.dos.GoodsDO;
import com.enation.app.javashop.core.member.model.vo.RegionVO;
import com.enation.app.javashop.core.shop.ShopErrorCode;
import com.enation.app.javashop.core.shop.model.dos.*;
import com.enation.app.javashop.core.shop.model.dto.PeekTime;
import com.enation.app.javashop.core.shop.model.enums.ShipFeeTypeEnum;
import com.enation.app.javashop.core.shop.model.enums.ShipTimeTypeEnum;
import com.enation.app.javashop.core.shop.model.enums.ShopTemplateTypeEnum;
import com.enation.app.javashop.core.shop.model.vo.*;
import com.enation.app.javashop.core.shop.service.ShipTemplateLocalManager;
import com.enation.app.javashop.core.shop.service.ShipTemplateManager;
import com.enation.app.javashop.core.shop.service.ShopManager;
import com.enation.app.javashop.framework.cache.Cache;
import com.enation.app.javashop.framework.context.UserContext;
import com.enation.app.javashop.framework.database.DaoSupport;
import com.enation.app.javashop.framework.exception.ServiceException;
import com.enation.app.javashop.framework.util.DateUtil;
import com.google.gson.Gson;
import org.apache.commons.lang.StringUtils;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.time.LocalTime;
import java.util.*;

/**
 * 同城配送模板
 *
 * @author zjp
 * @version v7.0.0
 * @since v7.0.0
 * 2018-03-28 21:44:49
 */
@Service
public class ShipTemplateLocalManagerImpl implements ShipTemplateLocalManager {

    @Autowired
    @Qualifier("memberDaoSupport")
    private DaoSupport daoSupport;

    @Autowired
    private Cache cache;

    @Autowired
    private ShopManager shopManager;

    @Autowired
    private AmqpTemplate amqpTemplate;


    /**
     * 保存同城配送模板
     *
     * @param shipLocalTemplateVO
     * @return
     */
    @Override
    public ShipLocalTemplateVO saveLocalTemplate(ShipLocalTemplateVO shipLocalTemplateVO) {
        // 查询商家信息
        Integer sellerId = UserContext.getSeller().getSellerId();
        shipLocalTemplateVO.setSellerId(sellerId);

        ShipTemplateDO t = new ShipTemplateDO();
        BeanUtils.copyProperties(shipLocalTemplateVO, t);
        t.setTemplateType(ShopTemplateTypeEnum.TONGCHENG.name());
        // 同城起送标准费用
        if (shipLocalTemplateVO.getFeeSettingVO().getFeeType().equals(ShipFeeTypeEnum.SECTION_DISTANCE.getIndex())) {
            t.setMinShipPrice(BigDecimal.valueOf(shipLocalTemplateVO.getFeeSettingVO().getDistanceSections().get(0).getShipPrice()));
        } else {
            t.setMinShipPrice(shipLocalTemplateVO.getFeeSettingVO().getBasePrice());
        }

        // 转换时间配置和费用配置
        composeTimeAndFee(shipLocalTemplateVO, t);

        // 保存
        this.daoSupport.insert(t);
        int id = this.daoSupport.getLastId("es_ship_template");
        shipLocalTemplateVO.setId(id);

        // 添加缓存
        cache.remove(CachePrefix.SHIP_TEMPLATE_LOCAL.getPrefix() + t.getSellerId());
        return shipLocalTemplateVO;
    }


    @Override
    public List<ShipLocalTemplateVO> getFromCacheBySellerId(Integer sellerId) {
        String key = CachePrefix.SHIP_TEMPLATE_LOCAL_ALL.getPrefix() + sellerId;
        // 从缓存取所有的分类
        List<ShipLocalTemplateVO> list = (List<ShipLocalTemplateVO>) cache.get(key);
        if (list == null) {
            // 调用初始化分类缓存方法
            String sql = "select * from es_ship_template where seller_id = ? and template_type=?";
            List<ShipTemplateDO> templateDOS = this.daoSupport.queryForList(sql, ShipTemplateDO.class, sellerId, ShopTemplateTypeEnum.TONGCHENG.name());
            for (ShipTemplateDO shipTemplateDO : templateDOS) {
                ShipLocalTemplateVO shipLocalTemplateVO = transToLocalTempVO(shipTemplateDO);
                list = Arrays.asList(shipLocalTemplateVO);
            }
        }
        cache.put(key, list);
        return list;
    }


    @Override
    public ShipLocalTemplateVO getFromCache(Integer templateId) {
        ShipLocalTemplateVO templateVO = (ShipLocalTemplateVO) this.cache.get(CachePrefix.SHIP_TEMPLATE_LOCAL.getPrefix() + templateId);
        if (templateVO == null) {
            // 调用初始化分类缓存方法
            templateVO = this.getFromDB(templateId);
            cache.put(CachePrefix.SHIP_TEMPLATE_LOCAL.getPrefix() + templateId, templateVO);
        }
        return templateVO;

    }

    /**
     * 查询同城配送模板
     *
     * @param templateId
     * @return
     */
    @Override
    public ShipLocalTemplateVO getFromDB(Integer templateId) {
        String sql = "select * from es_ship_template where id = ? ";
        ShipTemplateDO shipTemplateDO = this.daoSupport.queryForObject(sql, ShipTemplateDO.class, templateId);
        ShipLocalTemplateVO shipLocalTemplateVO = transToLocalTempVO(shipTemplateDO);
        return shipLocalTemplateVO;
    }

    /**
     * 编辑同城配送模板
     *
     * @param localTemplateVO
     * @return
     */
    @Override
    public Boolean editLocalTemplate(ShipLocalTemplateVO localTemplateVO) {
        ShipTemplateDO newTemp = new ShipTemplateDO();
        BeanUtils.copyProperties(localTemplateVO, newTemp);
        newTemp.setSellerId(UserContext.getSeller().getSellerId());
        composeTimeAndFee(localTemplateVO, newTemp);

        // 查询旧模板
        ShipTemplateDO originTemplate = this.getFromDB(localTemplateVO.getId());

        // 更新
        this.daoSupport.update(newTemp, newTemp.getId());


        // 添加缓存
        cache.remove(CachePrefix.SHIP_TEMPLATE_LOCAL.getPrefix() + newTemp.getId());
        cache.remove(CachePrefix.SHIP_TEMPLATE_LOCAL_ALL.getPrefix() + newTemp.getSellerId());
        cache.remove(CachePrefix.SHIP_TEMPLATE.getPrefix() + newTemp.getSellerId());

        //发送店铺信息改变消息
        amqpTemplate.convertAndSend(AmqpExchange.SHIP_TEMPLATE_CHANGE, AmqpExchange.SHIP_TEMPLATE_CHANGE + "_ROUTING", new ShipTemplateChangeMsg(originTemplate, newTemp));

        return true;
    }

    /**
     * 封装同城配送模板 时间和费用
     *
     * @param localTemplateVO
     * @param shipTemplateDO
     */
    private void composeTimeAndFee(ShipLocalTemplateVO localTemplateVO, ShipTemplateDO shipTemplateDO) {
        //校验同城配送费用模块 距离区间段 需要校核 最终距离与配送范围
        TemplateFeeSetting feeSettingVO = localTemplateVO.getFeeSettingVO();
        if (feeSettingVO.getFeeType() == ShipFeeTypeEnum.SECTION_DISTANCE.getIndex()) {
            List<DistanceSection> distanceSections = feeSettingVO.getDistanceSections();
            DistanceSection lastSection = distanceSections.get(distanceSections.size() - 1);
            if (lastSection.getEndDistance().compareTo(Double.valueOf(localTemplateVO.getShipRange())) != 0) {
                throw new ServiceException(ShopErrorCode.E240.code(), "距离区间最后段距离与配送范围不等");
            }
        }
        if(!CollectionUtils.isEmpty(feeSettingVO.getPeekTimes())){
            List<PeekTime> peekTimes = feeSettingVO.getPeekTimes();
            for (PeekTime peekTime : peekTimes) {
                if(peekTime.getPeekTimeStart()==null || peekTime.getPeekTimeEnd()==null || peekTime.getPeekTimePrice()==null){
                    feeSettingVO.setPeekTimes(null);
                    break;
                }
                peekTime.setStartTimeCount(DateUtil.transTimeToNumber(peekTime.getPeekTimeStart()));
                peekTime.setEndTimeCount(DateUtil.transTimeToNumber(peekTime.getPeekTimeEnd()));
            }
        }

        //校验同城配送时间模块
        TemplateTimeSetting timeSettingVO = localTemplateVO.getTimeSettingVO();
        if (timeSettingVO.getTimeType() == ShipTimeTypeEnum.SECTION_TIME.getIndex()) {
            List<TimeSection> timeSections = timeSettingVO.getTimeSections();
            ShopDetailDO shopDetail = shopManager.getShopDetail(localTemplateVO.getSellerId());
            if (StringUtils.isEmpty(shopDetail.getOpenEndTime())) {
                throw new ServiceException(ShopErrorCode.E242.code(), "店铺营业时间没有设置，请在店铺设置中选择【全天】或者【自定义】");
            }
            LocalTime openEndTime = DateUtil.transToLocalTime(shopDetail.getOpenEndTime());
            boolean flag = false;
            for (TimeSection timeSection : timeSections) {
                LocalTime shipTime = DateUtil.transToLocalTime(timeSection.getShipTime());
                if (openEndTime.isBefore(shipTime)) {
                    flag = true;
                    break;
                }
            }
            if (flag) {
                throw new ServiceException(ShopErrorCode.E242.code(), "当日最迟下单时间应当晚于营业结束时间 " + openEndTime.toString());
            }

        }

        shipTemplateDO.setFeeSetting(JSON.toJSONString(localTemplateVO.getFeeSettingVO()));
        shipTemplateDO.setTimeSetting(JSON.toJSONString(localTemplateVO.getTimeSettingVO()));
    }


    private ShipLocalTemplateVO transToLocalTempVO(ShipTemplateDO shipTemplateDO) {
        if (shipTemplateDO == null) {
            return null;
        }
        ShipLocalTemplateVO shipLocalTemplateVO = new ShipLocalTemplateVO();

        BeanUtils.copyProperties(shipTemplateDO, shipLocalTemplateVO);
        TemplateTimeSetting templateTimeSetting
                = JSON.parseObject(shipLocalTemplateVO.getTimeSetting(), new TypeReference<TemplateTimeSetting>() {
        });
        shipLocalTemplateVO.setTimeSettingVO(templateTimeSetting);
        TemplateFeeSetting templateFeeSetting
                = JSON.parseObject(shipLocalTemplateVO.getFeeSetting(), new TypeReference<TemplateFeeSetting>() {
        });
        shipLocalTemplateVO.setFeeSettingVO(templateFeeSetting);

        return shipLocalTemplateVO;
    }


}
